<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>


    <meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Integrating Browser History Manager with Server-side Pagination and Sorting</title>

<style type="text/css">
/*margin and padding on body element
  can introduce errors in determining
  element position and are not recommended;
  we turn them off as a foundation for YUI
  CSS treatments. */
body {
	margin:0;
	padding:0;
}
</style>

<link rel="stylesheet" type="text/css" href="../../build/fonts/fonts-min.css" />
<link rel="stylesheet" type="text/css" href="../../build/paginator/assets/skins/sam/paginator.css" />
<link rel="stylesheet" type="text/css" href="../../build/datatable/assets/skins/sam/datatable.css" />
<script type="text/javascript" src="../../build/yahoo-dom-event/yahoo-dom-event.js"></script>
<script type="text/javascript" src="../../build/connection/connection-min.js"></script>
<script type="text/javascript" src="../../build/json/json-min.js"></script>
<script type="text/javascript" src="../../build/history/history-min.js"></script>
<script type="text/javascript" src="../../build/element/element-min.js"></script>
<script type="text/javascript" src="../../build/paginator/paginator-min.js"></script>
<script type="text/javascript" src="../../build/datasource/datasource-min.js"></script>
<script type="text/javascript" src="../../build/event-delegate/event-delegate-min.js"></script>
<script type="text/javascript" src="../../build/datatable/datatable-min.js"></script>


<!--begin custom header content for this example-->
<style type="text/css">
/* custom styles for this example */
#yui-history-iframe {
  position:absolute;
  top:0; left:0;
  width:1px; height:1px; /* avoid scrollbars */
  visibility:hidden;
}
</style>

<!--end custom header content for this example-->

</head>

<body class="yui-skin-sam">


<h1>Integrating Browser History Manager with Server-side Pagination and Sorting</h1>

<div class="exampleIntro">
	<p>This example combines server-side pagination and sorting with the Browser
History Manager for the ability to bookmark states.</p>
			
</div>

<!--BEGIN SOURCE CODE FOR EXAMPLE =============================== -->

<iframe id="yui-history-iframe" src="assets/html/blank.html"></iframe>
<input id="yui-history-field" type="hidden">

<div id="dt-pag-nav"></div>
<div id="bhmintegration"></div>

<script type="text/javascript">
(function () {
    // Create the DataSource
    var myDataSource = new YAHOO.util.DataSource("assets/php/json_proxy.php?");
    myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSON;
    myDataSource.responseSchema = {
        resultsList: "records",
        fields: ["id","name","date","price"],
        metaFields: {
            totalRecords: "totalRecords",
            paginationRecordOffset : "startIndex",
            paginationRowsPerPage : "pageSize",
            sortKey: "sort",
            sortDir: "dir"
        }
    };

    // Create the Paginator
    var myPaginator = new YAHOO.widget.Paginator({
        containers : ["dt-pag-nav"],
        template : "{PreviousPageLink} {CurrentPageReport} {NextPageLink} {RowsPerPageDropdown}",
        pageReportTemplate : "Showing items {startIndex} - {endIndex} of {totalRecords}",
        rowsPerPageOptions : [10,25,50,100]
    });
    
    // Define Columns
    var myColumnDefs = [
        {key:"id", label:"ID", sortable:true},
        {key:"name", label:"Name", sortable:true},
        {key:"date", label:"Date", sortable:true},
        {key:"price", label:"Price", sortable:true}
    ];

    // DataTable configurations
    var myConfig = {
        paginator : myPaginator,
        dynamicData : true,
        initialLoad : false
    };

    // Instantiate DataTable
    var myDataTable = new YAHOO.widget.DataTable(
        "bhmintegration", myColumnDefs, myDataSource, myConfig
    );
    
    // Show loading message while page is being rendered
    myDataTable.showTableMessage(myDataTable.get("MSG_LOADING"), YAHOO.widget.DataTable.CLASS_LOADING);

    // Add the instances to the YAHOO.example namespace for inspection
    YAHOO.example.BHMIntegration = {
        myPaginator  : myPaginator,
        myDataSource : myDataSource,
        myDataTable  : myDataTable
    };
    
    // Integrate with Browser History Manager
    var History = YAHOO.util.History;

    // Define a custom function to route sorting through the Browser History Manager
    var handleSorting = function (oColumn) {
        // Calculate next sort direction for given Column
        var sDir = this.getColumnSortDir(oColumn);
        
        // The next state will reflect the new sort values
        // while preserving existing pagination rows-per-page
        // As a best practice, a new sort will reset to page 0
        var newState = generateRequest(0, oColumn.key, sDir, this.get("paginator").getRowsPerPage());

        // Pass the state along to the Browser History Manager
        History.navigate("myDataTable", newState);
    };
    myDataTable.sortColumn = handleSorting;

    // Define a custom function to route pagination through the Browser History Manager
    var handlePagination = function(state) {
        // The next state will reflect the new pagination values
        // while preserving existing sort values
        // Note that the sort direction needs to be converted from DataTable format to server value
        var sortedBy  = this.get("sortedBy"),
            newState = generateRequest(
            state.recordOffset, sortedBy.key, sortedBy.dir, state.rowsPerPage
        );

        // Pass the state along to the Browser History Manager
        History.navigate("myDataTable", newState);
    };
    // First we must unhook the built-in mechanism...
    myPaginator.unsubscribe("changeRequest", myDataTable.onPaginatorChangeRequest);
    // ...then we hook up our custom function
    myPaginator.subscribe("changeRequest", handlePagination, myDataTable, true);

    // Update payload data on the fly for tight integration with latest values from server 
    myDataTable.doBeforeLoadData = function(oRequest, oResponse, oPayload) {
        var meta = oResponse.meta;
        oPayload.totalRecords = meta.totalRecords || oPayload.totalRecords;
        oPayload.pagination = {
            rowsPerPage: meta.paginationRowsPerPage || 10,
            recordOffset: meta.paginationRecordOffset || 0
        };
        oPayload.sortedBy = {
            key: meta.sortKey || "id",
            dir: (meta.sortDir) ? "yui-dt-" + meta.sortDir : "yui-dt-asc" // Convert from server value to DataTable format
        };
        return true;
    };
    
    // Returns a request string for consumption by the DataSource
    var generateRequest = function(startIndex,sortKey,dir,results) {
        startIndex = startIndex || 0;
        sortKey   = sortKey || "id";
        dir   = (dir) ? dir.substring(7) : "asc"; // Converts from DataTable format "yui-dt-[dir]" to server value "[dir]"
        results   = results || 10;
        return "results="+results+"&startIndex="+startIndex+"&sort="+sortKey+"&dir="+dir;
    };

    // Called by Browser History Manager to trigger a new state
    var handleHistoryNavigation = function (request) {
        // Sends a new request to the DataSource
        myDataSource.sendRequest(request,{
            success : myDataTable.onDataReturnSetRows,
            failure : myDataTable.onDataReturnSetRows,
            scope : myDataTable,
            argument : {} // Pass in container for population at runtime via doBeforeLoadData
        });
    };

    // Calculate the first request
    var initialRequest = History.getBookmarkedState("myDataTable") || // Passed in via URL
                       generateRequest(); // Get default values

    // Register the module
    History.register("myDataTable", initialRequest, handleHistoryNavigation);

    // Render the first view
    History.onReady(function() {
        // Current state after BHM is initialized is the source of truth for what state to render
        var currentState = History.getCurrentState("myDataTable");
        handleHistoryNavigation(currentState);
    });

    // Initialize the Browser History Manager.
    YAHOO.util.History.initialize("yui-history-field", "yui-history-iframe");
})();
</script>

<!--END SOURCE CODE FOR EXAMPLE =============================== -->

</body>
</html>
